<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript">
            //<![CDATA[
var dropbox;
var img;
var view;

function init() {
    dropbox = document.getElementById("canPGM");
    dropbox.addEventListener("dragenter", dragenter, false);
    dropbox.addEventListener("dragover", dragover, false);
    dropbox.addEventListener("drop", drop, false);
}

function dragenter(e) {
    e.stopPropagation();
    e.preventDefault();
}

function dragover(e) {
    e.stopPropagation();
    e.preventDefault();
}

function drop(e) {
    e.stopPropagation();
    e.preventDefault();

    var dt = e.dataTransfer;
    var files = dt.files;

    handleFiles(files);
}

function handleFiles(files) {
    if (files.length == 1) {
        var reader = new FileReader();
        reader.readAsText(files[0]);
        reader.onloadend = function(event) {
            img = new tgd.Utilities.Images.PGM(files[0].name, reader.result);
            view = new tgd.Utilities.Images.PGM.View(document.getElementById("canPGM"), img);
        }
    } else {
        console.error("Assuming that only 1 file will be dropped.");
    }
}

var tgd = tgd || {};
tgd.Utilities = tgd.Utilities || {};
tgd.Utilities.Images = tgd.Utilities.Images || {};

/*
 * http://netpbm.sourceforge.net/doc/pgm.html
 *
 * Assumptions:
 *      Max Gray Value [1-255]
 *      Only one image per file
 *      No comments or supperflous whitespace
 *      Lines seperated with \n
 *
 *  P5
 *  2 2
 *  255
 *  1!aA
 */
tgd.Utilities.Images.PGM = function (name, data) {
    var _name = name;
    var _type;
    var _width;
    var _height;
    var _maxGrayValue;
    var _raw = [];

    //var lines = data.match(/^.*$/gm)
    var lines = data.split("\n");
    var r = 0, c = 0, idx = 0;
    var line;

    _type = lines[0].substr(0, 2);
    _width = parseInt(lines[1].split(' ')[0]);
    _height = parseInt(lines[1].split(' ')[1]);
    _maxGrayValue = parseInt(lines[2]);

    this.__defineGetter__("Name", function() { return _name; });
    this.__defineGetter__("Type", function() { return _type; });
    this.__defineGetter__("Width", function() { return _width; });
    this.__defineGetter__("Height", function() { return _height; });
    this.__defineGetter__("MaxGrayValue", function() { return _maxGrayValue; });
    this.__defineGetter__("Bytes", function() { return _width * _height; });
    this.__defineGetter__("RawData", function() { return _raw; });

    for (var i = 3; i < lines.length; ++i) {
        line = lines[i];
        
        for (var j = 0; j < line.length; ++j) {
            c = idx % _width;
            r = parseInt(idx / _width);

            if (c === 0) {
                _raw[r] = [];
            }

            _raw[r][c] = line.charCodeAt(j);

            ++idx;
        }
    }
}

tgd.Utilities.Images.PGM.View = function (canvas, data) {
    var _canvasElement = canvas;
    var _canvas = _canvasElement.getContext("2d");
    var _data = data;

    _canvasElement.height = _data.Height;
    _canvasElement.width = _data.Width;

    document.getElementById("lblName").textContent = _data.Name;
    document.getElementById("lblSize").textContent = _data.Bytes;
    document.getElementById("lblType").textContent = _data.Type;
    document.getElementById("lblHeight").textContent = _data.Height;
    document.getElementById("lblWidth").textContent = _data.Width;
    document.getElementById("lblGray").textContent = _data.MaxGrayValue;

    var currentRow = 0;
    /* For performance, reference properties here. */
    var height = _data.Height;
    var width = _data.Width;
    var raw = _data.RawData;
    
    var foo = function() {
        var color;
        var rawRow = raw[currentRow];

        if (currentRow < height) {
            for (var col = 0; col < width; ++col) {
                color = rawRow[col];
                _canvas.fillStyle = "rgb(" + color + "," + color + "," + color + ")";
                _canvas.fillRect(col, currentRow, 1, 1);
                if (color > 255) {
                    _canvas.fillStyle = "#0f0";
                    _canvas.fillRect(col, currentRow, 1, 1);
                }
            }

            setTimeout(foo, 0);
            ++currentRow;
        }
    }

    setTimeout(foo, 0);
}

    //]]>
        </script>
        <style type="text/css">
            body{background:#000;margin:0;font-size:14pt;color:#fff;}
            #dropbox{background:#000;text-align:left;vertical-align:top;color:#666;border:solid 1px #A4C639;margin:5px auto;padding:5px;width:400px;}
            #dropbox span{font-weight:bold;}
            canvas:-moz-drag-over{border-color: #a4c639;}
            #panCanvasHolder{text-align:center;margin:10px;}
            canvas{border:5px solid #fff;}
        </style>
    </head>
    <body onload="init();">
        <div id="panCanvasHolder">
            <canvas id="canPGM"></canvas>
        </div>
        <div id="dropbox">
            <div>
                Name: <span id="lblName"></span>
            </div>
            <div>
                Size: <span id="lblSize"></span> bytes
            </div>
            <div>
                Type: <span id="lblType"></span>
            </div>
            <div>
                Height: <span id="lblHeight"></span>
            </div>
            <div>
                Width: <span id="lblWidth"></span>
            </div>
            <div>
                Max Gray Value: <span id="lblGray"></span>
            </div>
        </div>
    </body>
</html>
